package org.easy.core.util;


import com.alibaba.fastjson.JSON;

import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: lichaojie
 * @Description: 通用判断引用是否空, 类型转换封装
 */
public class ObjectUtil {

    private final static int DEFAULT_INTEGER = 0;
    private final static long DEFAULT_LONG = 0L;
    private final static float DEFAULT_FLOAT = 0f;
    private final static double DEFAULT_DOUBLE = 0d;
    private final static boolean DEFAULT_BOOLEAN = false;
    private final static String DEFAULT_STRING = "";


    /**
     * 判断字符串,集合,字典,数组 是否非空或者无元素,
     * 封装后可以不用关心不同对象的不同判空方法
     * <pre>
     * 通常写法
     * //如果Object为Collection
     * if (null==list||list.size()==0){
     * return;
     * }
     *
     * //如果Object为String
     * if (string==null||string.length()==0){
     * return;
     * }
     *
     * ...等等
     *
     * 封装后
     * if(ObjectUtils.isEmpty(obj)){
     *     return;
     * }
     * <pre/>
     *
     * @param object 对象
     * @return
     */
    public static boolean isEmpty(Object object) {
        if (null == object) {
            return true;
        }
        try {
            if (object instanceof CharSequence) {
                CharSequence cs = (CharSequence) object;
                return isEmpty(cs.toString().trim());
            }
            if (object instanceof Collection) {
                return ((Collection) object).isEmpty();
            }
            if (object instanceof Map) {
                return ((Map) object).isEmpty();
            }
            if (object.getClass().isArray()) {
                return Array.getLength(object) <= 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
        return false;
    }


    /**
     * 对象转 int,避免发生错误和空指针, 异常时返回0
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Integer.valueOf(String.valueOf(object));
     * } else {
     * result = 0;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * int result=ObjectUtils.toInt(object);
     * <pre/>
     * @param object 对象
     * @return
     */
    public static int toInt(Object object) {
        return toInt(object, DEFAULT_INTEGER);
    }

    /**
     * 对象转 int,避免发生错误和空指针,defaultValue
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Integer.valueOf(String.valueOf(object));
     * } else {
     * result = 0;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * int result=ObjectUtils.toInt(object,0);
     * <pre/>
     * @param object       对象
     * @param defaultValue 默认值
     * @return
     */
    public static int toInt(Object object, int defaultValue) {
        if (null == object) {
            return defaultValue;
        }
        try {
            if (object instanceof Integer) {
                defaultValue = (Integer) object;
            } else if (object instanceof Long) {
                defaultValue = ((Long) object).intValue();
            } else if (object instanceof Short) {
                defaultValue = ((Short) object).intValue();
            } else {
                defaultValue = toInt(object.toString(), defaultValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return defaultValue;
        }

        return defaultValue;
    }

    /**
     * 对象转 int,避免发生错误和空指针,defaultValue
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Integer.valueOf(String.valueOf(object));
     * } else {
     * result = 0;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * int result=ObjectUtils.toInt(object,0);
     * <pre/>
     * @param str       对象
     * @param defaultValue 默认值
     * @return
     */
    public static int toInt(String str, int defaultValue) {
        if (str == null) {
            return defaultValue;
        } else {
            try {
                return Integer.parseInt(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return defaultValue;
            }
        }
    }

    /**
     * 对象转long,避免发生错误和空指针,异常时返回 0
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Long.valueOf(String.valueOf(object));
     * } else {
     * result = 0L;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * long result=ObjectUtils.toLong(object);
     * <pre/>
     * @param object 对象
     * @return
     */
    public static long toLong(Object object) {
        return toLong(object, DEFAULT_LONG);
    }

    /**
     * 对象转long,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Long.valueOf(String.valueOf(object));
     * } else {
     * result = 0L;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * long result=ObjectUtils.toLong(object,0L);
     * <pre/>
     *
     * @param object       对象
     * @param defaultValue 默认值
     * @return
     */
    public static long toLong(Object object, long defaultValue) {
        if (null == object) {
            return defaultValue;
        }
        try {
            if (object instanceof Integer) {
                defaultValue = ((Integer) object).longValue();
            } else if (object instanceof Long) {
                defaultValue = (Long) object;
            } else if (object instanceof Short) {
                defaultValue = ((Short) object).longValue();
            } else {
                defaultValue = toLong(object.toString(), defaultValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return defaultValue;
        }

        return defaultValue;
    }

    /**
     * 对象转long,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Long.valueOf(String.valueOf(object));
     * } else {
     * result = 0L;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * long result=ObjectUtils.toLong(object,0L);
     * <pre/>
     *
     * @param str       对象
     * @param defaultValue 默认值
     * @return
     */
    public static long toLong(String str, long defaultValue) {
        if (str == null) {
            return defaultValue;
        } else {
            try {
                return Long.parseLong(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return defaultValue;
            }
        }
    }

    /**
     * 对象转float,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Float.valueOf(String.valueOf(object));
     * } else {
     * result = 0F;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * float result=ObjectUtils.toFloat(object);
     * <pre/>
     * @param object 对象
     * @return
     */
    public static float toFloat(Object object) {
        return toFloat(object, DEFAULT_FLOAT);
    }

    /**
     * 对象转float,避免发生错误和空指针,异常时返回 defaultValue
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Float.valueOf(String.valueOf(object));
     * } else {
     * result = 0F;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * float result=ObjectUtils.toFloat(object,0F);
     * <pre/>
     * @param object       对象
     * @param defaultValue 默认值
     * @return
     */
    public static float toFloat(Object object, float defaultValue) {
        if (null == object) {
            return defaultValue;
        }
        try {
            if (object instanceof Integer) {
                defaultValue = ((Integer) object).floatValue();
            } else if (object instanceof Long) {
                defaultValue = (Long) object;
            } else if (object instanceof Short) {
                defaultValue = ((Short) object).floatValue();
            } else {
                defaultValue = toFloat(object.toString(), defaultValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return defaultValue;
        }

        return defaultValue;
    }

    /**
     * 对象转float,避免发生错误和空指针,异常时返回 defaultValue
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Float.valueOf(String.valueOf(object));
     * } else {
     * result = 0F;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * float result=ObjectUtils.toFloat(object,0F);
     * <pre/>
     * @param str       对象
     * @param defaultValue 默认值
     * @return
     */
    public static float toFloat(String str, float defaultValue) {
        if (str == null) {
            return defaultValue;
        } else {
            try {
                return Float.parseFloat(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return defaultValue;
            }
        }
    }


    /**
     * 对象转toDouble,避免发生错误和空指针,异常时返回 defaultValue
     *
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Double.valueOf(String.valueOf(object));
     * } else {
     * result = 0D;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * double result=ObjectUtils.toDouble(object);
     * <pre/>
     * @param object 对象
     * @return
     */
    public static double toDouble(Object object) {
        return toDouble(object, DEFAULT_DOUBLE);
    }


    /**
     * 对象转double,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法 对象转double
     * int result;
     * try {
     * if (null != object) {
     * result = Double.valueOf(String.valueOf(object));
     * } else {
     * result = 0D;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * double result=ObjectUtils.toDouble(object,0D);
     * <pre/>
     * @param object       对象
     * @param defaultValue 默认值
     * @return
     */
    public static double toDouble(Object object, double defaultValue) {
        if (null == object) {
            return defaultValue;
        }
        try {
            if (object instanceof Integer) {
                defaultValue = ((Integer) object).doubleValue();
            } else if (object instanceof Long) {
                defaultValue = (Long) object;
            } else if (object instanceof Short) {
                defaultValue = ((Short) object).doubleValue();
            } else {
                defaultValue = toDouble(object.toString(), defaultValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return defaultValue;
        }
        return defaultValue;
    }

    /**
     * 对象转double,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法 对象转double
     * int result;
     * try {
     * if (null != object) {
     * result = Double.valueOf(String.valueOf(object));
     * } else {
     * result = 0D;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * double result=ObjectUtils.toDouble(object,0D);
     * <pre/>
     * @param str       对象
     * @param defaultValue 默认值
     * @return
     */
    public static double toDouble(String str, double defaultValue) {
        if (str == null) {
            return defaultValue;
        } else {
            try {
                return Double.parseDouble(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
                return defaultValue;
            }
        }
    }

    /**
     * 对象转boolean,避免发生错误和空指针,异常时返回false
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Boolean.valueOf(String.valueOf(object));
     * } else {
     * result = false;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * double result=ObjectUtils.toBoolean(object);
     * </pre>
     *
     * @param object 对象
     * @return
     */
    public static boolean toBoolean(Object object) {
        return toBoolean(object, DEFAULT_BOOLEAN);
    }

    /**
     * 对象转boolean,避免发生错误和空指针,异常时返回 defaultValue
     * <pre>
     * 通常写法
     * int result;
     * try {
     * if (null != object) {
     * result = Boolean.valueOf(String.valueOf(object));
     * } else {
     * result = false;
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * double result=ObjectUtils.toBoolean(object);
     * </pre>
     *
     * @param object       对象
     * @param defaultValue 默认值
     * @return
     */
    public static boolean toBoolean(Object object, boolean defaultValue) {
        if (null == object) {
            return defaultValue;
        }

        if ("true".equalsIgnoreCase(String.valueOf(object))) {
            return true;
        } else if ("false".equalsIgnoreCase(String.valueOf(object))) {
            return false;
        } else {
            return defaultValue;
        }
    }


    /**
     * 对象转toDouble,避免发生错误和空指针,异常时返回 defaultValue
     *
     * <pre>
     * 通常写法
     * String result;
     * try {
     * if (null != object) {
     * result = String.valueOf(object);
     * } else {
     * result = "";
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * String result=ObjectUtils.toString(object);
     * <pre/>
     * @param object 对象
     * @return
     */
    public static String toString(Object object) {
        return toString(object, DEFAULT_STRING);
    }


    /**
     * 对象转toDouble,避免发生错误和空指针,异常时返回 defaultValue
     *
     * <pre>
     * 通常写法
     * String result;
     * try {
     * if (null != object) {
     * result = String.valueOf(object);
     * } else {
     * result = "";
     * }
     * }catch (Exception e){
     * e.printStackTrace();
     * }
     *
     * 封装后
     * String result=ObjectUtils.toString(object);
     * <pre/>
     * @param object 对象
     * @param defaultValue 默认值
     * @return
     */
    public static String toString(Object object, String defaultValue) {
        if (null == object) {
            return defaultValue;
        }
        return String.valueOf(object);
    }


    /**
     * String转java基本类型
     *
     * @param cls
     * @param val
     * @return
     */
    public static Object stringToObject(Class<?> cls, String val) {
        if (cls == null || val.length() == 0) return null;
        if (cls == int.class || cls == Integer.class) return Integer.parseInt(val);
        if (cls == byte.class || cls == Byte.class) return Byte.parseByte(val);
        if (cls == char.class) return val.toCharArray()[0];
        if (cls == short.class || cls == Short.class) return Short.parseShort(val);
        if (cls == long.class || cls == Long.class) return Long.parseLong(val);
        if (cls == float.class || cls == Float.class) return Float.parseFloat(val);
        if (cls == double.class || cls == Double.class) return Double.parseDouble(val);
        if (cls == BigDecimal.class) return new BigDecimal(val);
        return null;
    }

    /**
     * 字符串判空
     *
     * @param cs
     * @return
     */
    public static boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * 字符串判非空
     *
     * @param cs
     * @return
     */
    public static boolean isNotEmpty(CharSequence cs) {
        return !isEmpty(cs);
    }

    /**
     * 使用Fastjson进行对象的深拷贝
     *
     * @param <T>    泛型类型
     * @param source 原始对象
     * @return 拷贝后的新对象
     */
    public static <T> T copy(Object source, Class<T> target) {
        if (source == null || target == null) {
            return null;
        }
        return JSON.parseObject(JSON.toJSONString(source), target);
    }

    public static <T, E> List<T> copyList(List<E> source, Class<T> target) {
        if (source == null || target == null) {
            return new ArrayList<>();
        }

        return source.stream().map(e -> ObjectUtil.copy(e, target)).collect(Collectors.toList());
    }


}
